// Copyright 2022 jeff.li. and/or its affiliates.

#include <tbir/runtime/generator/generator_ref.h>

#include <tbir/runtime/container/itertor_private.h>
#include <tbir/runtime/generator/generator_private.h>
#include <tbir/runtime/memory.h>

namespace tbir::runtime {

/******************************************************************************
 * Generator
 *****************************************************************************/

#define DEFINE_GENERATOR_OBJECT_REF(Name, ResultType)                                \
  Name::Name(std::shared_ptr<BaseGenerator<ResultType>> generator) {                 \
    data_ = make_object<Name##Node>(Name::GAdapter(std::move(generator)));           \
  }                                                                                  \
  Name::Name(GAdapter generator) {                                                   \
    data_ = make_object<Name##Node>(std::move(generator));                           \
  }                                                                                  \
  Name::GAdapter* Name::GetGenerator() const {                                       \
    MX_CHECK_DPTR(Name);                                                             \
    return &d->generator_;                                                           \
  }                                                                                  \
  Iterator Name::iter() const {                                                      \
    return MakeGenericIterator(*this, begin(), end());                               \
  }                                                                                  \
  template <>                                                                        \
  bool IsConvertible<Name>(const Object* node) {                                     \
    return node ? node->IsInstance<Name::ContainerType>() : Name::_type_is_nullable; \
  }                                                                                  \
  std::ostream& operator<<(std::ostream& os, Name const& n) {                        \
    os << #Name;                                                                     \
    return os;                                                                       \
  }

    DEFINE_GENERATOR_OBJECT_REF(BoolGenerator, bool);
    DEFINE_GENERATOR_OBJECT_REF(Int32Generator, int32_t);
    DEFINE_GENERATOR_OBJECT_REF(Int64Generator, int64_t);
    DEFINE_GENERATOR_OBJECT_REF(Float32Generator, float);
    DEFINE_GENERATOR_OBJECT_REF(Float64Generator, double);
    DEFINE_GENERATOR_OBJECT_REF(RTValueGenerator, RTValue);

}  // namespace tbir::runtime
